/**
* Copyright (c) 2015, 爱wifi（版权声明）
*
* @file ngx_http_mytest_module.c
* @brief 文件的简单介绍
*
* 文件的详细介绍
*
* @author: yuhaiyang
* @date: 2016/3/10
*/
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>


////////////////////////////内部函数说明///////////////////////////////////

/**
 * @brief ngx_http_mytest_handler
 * @param r http 请求的参数
 * @return 处理结果
 */
static ngx_int_t ngx_http_mytest_handler( ngx_http_request_t* r );

/**
 * @brief ngx_http_mytest
 * @param cf 配置文件信息
 * @param cmd
 * @param conf
 * @return
 */
static char* ngx_http_mytest( ngx_conf_t* cf, ngx_command_t* cmd, void* conf );




static ngx_command_t ngx_http_mytest_commands[] = {
  {
        //配置项名称
        ngx_string("mytest"),
        NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF
        | NGX_HTTP_LOC_CONF | NGX_HTTP_LMT_CONF | NGX_CONF_NOARGS,
        ngx_http_mytest,
        NGX_HTTP_LOC_CONF_OFFSET,
        0,
        NULL
    },
    ngx_null_command
};


//没有什么工作是奥要在 http 框架完成的那么毁掉函数设置为NULL
static ngx_http_module_t ngx_http_mytest_module_ctx =
{
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL
};



ngx_module_t ngx_http_mytest_module =
{
    NGX_MODULE_V1,
    &ngx_http_mytest_module_ctx,
    ngx_http_mytest_commands,
    NGX_HTTP_MODULE,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NGX_MODULE_V1_PADDING
};


//配置项响应函数
static char*
ngx_http_mytest( ngx_conf_t* cf, ngx_command_t* cmd, void* conf )
{
    ngx_http_core_loc_conf_t* clcf;
    clcf = ngx_http_conf_get_module_loc_conf( cf, ngx_http_core_module );

    //设置处理请求的方法，HTTP框架在处理用户请求进行到NGX_HTTP_CONTENT_PHASE阶段时
    // 如果主机域名、URI和mytest模块所在配置块名称相同，就会调用函数ngx_http_mytest_handler
    clcf->handler = ngx_http_mytest_handler;
    return NGX_CONF_OK;
}


//请求的所有信息都存在了　ngx_http_request_t 里。
static ngx_int_t ngx_http_mytest_handler( ngx_http_request_t* r )
{
    // 请求的方法必须为GET或者HEAD
     if (!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD)))
       return NGX_HTTP_NOT_ALLOWED;

     // 丢弃请求中的包体
     ngx_int_t rc = ngx_http_discard_request_body(r);
     if (rc != NGX_OK)
       return rc;

     ngx_str_t type = ngx_string("text/plain");
     ngx_str_t response = ngx_string("Hello World yu!");	// 包体内容
     // 设置响应的HTTP头部
     r->headers_out.status = NGX_HTTP_OK;		   // 返回的响应码
     r->headers_out.content_length_n = response.len;	// 响应包体长度
     r->headers_out.content_type = type;				// Content-Type

     rc = ngx_http_send_header(r); // 发送HTTP头部
     if (rc == NGX_ERROR || rc > NGX_OK || r->header_only)
       return rc;

      // 如果响应不包含包体，则在此处可以直接返回rc

     // 分配响应包体空间，因为是异步发送，所以不要从栈中获得空间
     ngx_buf_t *b = ngx_create_temp_buf(r->pool, response.len);

     if (b == NULL)
       return NGX_HTTP_INTERNAL_SERVER_ERROR;

     ngx_memcpy(b->pos, response.data, response.len);
     b->last = b->pos + response.len;  // 指向数据末尾
     b->last_buf = 1;					// 声明这是最后一块缓冲区

     ngx_chain_t out;
     out.buf = b;
     out.next = NULL;

     return ngx_http_output_filter(r, &out);   // 向用户发送响应包
}
